<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Menus</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Android, programming, menus, tutorial, 
Java, mobile development">
<meta name="description" content="In this chapter of the Android tutorial, we will work with 
menus.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content2">


<a href="/" title="Home">Home</a>&nbsp;
<a href=".." title="Home">Contents</a>


<h1>Menus</h1>


<p>
In this chapter of the Android development tutorial we will work with menus. 
Menus group available commands of an application. In traditional desktop 
applications menus are part of a menubar which is located mostly in the top area
of the application. Context or popup menus are special cases of menus.
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
There are three kinds of menus in Android. Options menu, context menu and popup menu.
The <b>options menu</b> is the primary collection of menu items for an activity. In the
options menu we should have commands that have global impact on the applications. For example
a Settings menu. It is displayed either at the top or at the bottom of the activity.
The <b>context menu</b> shows menu items in a specific context. 
For example for ListView items. It is shown when the user performs a long-click 
on an element. A <b>popup menu</b> displays a list of items in a vertical list that's 
anchored to the view that invoked the menu. It appears below the anchor view if there is room, 
or above the view otherwise. It should relate to regions of content in the activity.
</p>

<p>
Menus can be created manually by coding or they can be defined in an XML file. 
If we define our menus in an XML file we use the <i>MenuInflater</i> object to 
create menus from the XML file.
</p>


<h2>Options menu</h2>
 
<p>
Our options menu will have two menu items. When we select a menu item a Toast window
is shown with the name of the selected menu item. The options menu is displayed
after we click on the menu button. 
</p>

<p>
The manifest file is not modified in this example.
</p>


<img src="/img/java/android/menubutton.png" alt="Menu button">
<div class="figure">
Figure: Menu button
</div>
<br>

<div class="codehead">main.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &gt;
    
  &lt;TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/message" /&gt;
    
&lt;/LinearLayout&gt;
</pre>

<p>
In the <i>main.xml</i> layout file, we have one TextView widget.
It will display a welcome message.
</p>

<div class="codehead">strings.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
    &lt;string name="app_name"&gt;OptionsMenu&lt;/string&gt;
    &lt;string name="message"&gt;Demonstrating Options Menu&lt;/string&gt;
    &lt;string name="om1"&gt;Settings&lt;/string&gt;
    &lt;string name="om2"&gt;Tools&lt;/string&gt;
&lt;/resources&gt;
</pre>

<p>
This is <i>strings.xml</i> file.
</p>

<div class="codehead">options_menu.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  &lt;item android:id="@+id/settings"
    android:title="@string/om1" /&gt;
  &lt;item android:id="@+id/tools"
    android:title="@string/om2" /&gt;
&lt;/menu&gt;
</pre>

<p>
This is <i>options_menu.xml</i> file. It defines two menu items. The file
is located in the res/menu/ subdirectory.
</p>

<div class="codehead">MainActivity.java</div>
<pre class="code">
package com.zetcode.opmenu;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch (item.getItemId()) 
        {
            case R.id.settings:
                Toast.makeText(MainActivity.this, "Settings menu selected.", 
                    Toast.LENGTH_SHORT).show();
                return true;

            case R.id.tools:
                Toast.makeText(MainActivity.this, "Tools menu selected.", 
                    Toast.LENGTH_SHORT).show();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }
}
</pre>

<p>
To enable an options menu in an activity, we need to override the <code>onCreateOptionsMenu()</code>
and the <code>onOptionsItemSelected()</code> methods.
</p>

<pre class="explanation">
@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.options_menu, menu);
    return true;
}
</pre>

<p>
Inside the <code>onCreateOptionsMenu()</code> method, we build the options menu from
the options_menu.xml file. We use the <code>MenuInflater</code> class to do the job.
</p>

<pre class="explanation">
@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
...
}
</pre>

<p>
The <code>onOptionsItemSelected()</code> method handles the click events on the
menu items.
</p>

<pre class="explanation">
case R.id.settings:
    Toast.makeText(MainActivity.this, "Settings menu selected.", 
        Toast.LENGTH_SHORT).show();
    return true;
</pre>

<p>
In case of the selection of the Settings menu item we show a Toast window
with "Settings menu selected" message.
</p>


<img src="/img/java/android/optionsmenu.png" alt="Options menu at the bottom of the activity">
<div class="figure">
Figure: Options menu at the bottom of the activity
</div>


<h2>Context menu</h2>
 
<p>
We have a ListView with the names of our planets. A long-click on an element
will show a context menu with tree options. Delete, Uppercase and Lowercase. 
</p>

<p>
The manifest file is not modified.
</p>


<div class="codehead">main.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &gt;
    
    &lt;ListView 
      android:id="@+id/lvId"
      android:layout_width="fill_parent"   
      android:layout_height="fill_parent" /&gt;  
      
&lt;/LinearLayout&gt;
</pre>

<p>
This is <i>main.xml</i> file. It contais a ListView widget.
</p>

<div class="codehead">strings.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
    &lt;string name="app_name"&gt;ContextMenu&lt;/string&gt;
    &lt;string-array name="planets"&gt;
        &lt;item&gt;Mercury&lt;/item&gt;
        &lt;item&gt;Venus&lt;/item&gt;
        &lt;item&gt;Earth&lt;/item&gt;
        &lt;item&gt;Mars&lt;/item&gt;
        &lt;item&gt;Jupiter&lt;/item&gt;
        &lt;item&gt;Saturn&lt;/item&gt;
        &lt;item&gt;Uranus&lt;/item&gt;
        &lt;item&gt;Neptune&lt;/item&gt;
        &lt;item&gt;Pluto&lt;/item&gt;
    &lt;/string-array&gt;     
&lt;/resources&gt;
</pre>

<p>
This is the <i>strings.xml</i> resource file. 
</p>

<div class="codehead">row.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="20sp"&gt;
&lt;/TextView&gt;
</pre>

<p>
This is the <i>row.xml</i> resource file. Each row of a ListView consists of
a single TextView.
</p>

<div class="codehead">MainActivity.java</div>
<pre class="code">
package com.zetcode.conmenu;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;  
import android.widget.ListView;  
import android.view.View;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;

import java.util.Arrays;
import java.util.ArrayList;


public class MainActivity extends Activity
{
    private ListView lv;  
    private ArrayAdapter&lt;String&gt; la; 

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        setupUI();
    }

    public void setupUI()
    { 
        lv = (ListView) findViewById(R.id.lvId);  
        String[] planets = getResources().getStringArray(R.array.planets); 
        ArrayList&lt;String&gt; lst = new ArrayList&lt;String&gt;();
        lst.addAll(Arrays.asList(planets));

        la = new ArrayAdapter&lt;String&gt;(this, R.layout.row, lst);
        lv.setAdapter(la);
        registerForContextMenu(lv);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, 
        ContextMenuInfo menuInfo) 
    {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) 
    {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        
        int pos = info.position;
        String i = la.getItem(pos);

        switch (item.getItemId()) 
        {
            case R.id.delId:
                la.remove(i);
                return true;

            case R.id.upId:               
                String upln = i.toUpperCase();
                la.remove(i);
                la.insert(upln, pos); 
                return true;

            case R.id.loId:
                String lpln = i.toLowerCase();
                la.remove(i);
                la.insert(lpln, pos);          
                return true;

            default:
                return super.onContextItemSelected(item);
        }
    }
}
</pre>

<p>
In order to implement the context menu, we have to override the <code>onCreateContextMenu()</code> and
the <code>onContextItemSelected()</code> methods. We also need to call the <code>registerForContextMenu()</code>
method for a specific view.
</p>

<pre class="explanation">
String[] planets = getResources().getStringArray(R.array.planets); 
ArrayList&lt;String&gt; lst = new ArrayList&lt;String&gt;();
lst.addAll(Arrays.asList(planets));
</pre>

<p>
We will be deleting items of the ListView. Therefore, we need to use an ArrayList. Otherwise the list would be
read-only.
</p>

<pre class="explanation">
registerForContextMenu(lv);
</pre>

<p>
The context menu is registered for the ListView widget.
</p>

<pre class="explanation">
@Override
public void onCreateContextMenu(ContextMenu menu, View v, 
    ContextMenuInfo menuInfo) 
{
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.context_menu, menu);
}
</pre>

<p>
In the <code>onCreateContextMenu()</code> method we build
the context menu from the context_menu.xml file.
</p>

<pre class="explanation">
@Override
public boolean onContextItemSelected(MenuItem item) 
{
...
}
</pre>

<p>
The <code>onContextItemSelected()</code> reacts to list item selection events.
</p>

<pre class="explanation">
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();

int pos = info.position;
String i = la.getItem(pos);
</pre>

<p>
To find out more about the selected item, we use the <code>AdapterContextMenuInfo</code> class.
We get the position and the text of the selected item.
</p>

<pre class="explanation">
case R.id.delId:
    la.remove(i);
    return true;
</pre>

<p>
If we select the Delete context menu option, we remove the item
from the ArrayAdapter.
</p>

<pre class="explanation">
case R.id.upId:               
    String upln = i.toUpperCase();
    la.remove(i);
    la.insert(upln, pos); 
    return true;
</pre>

<p>
For the Uppercase option, we modify the string, remove the original one
and insert a new one.
</p>


<img src="/img/java/android/contextmenu.png" alt="Context menu with three options">
<div class="figure">
Figure: Context menu with three options
</div>


<h2>Popup menu</h2>
 
<p>
The example shows a PopupMenu after clicking on a button.
</p>

<p>
The manifest file is not modified.
</p>


<div class="codehead">main.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    &gt;
    
  &lt;Button
      android:id="@+id/btnId"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      android:layout_marginTop="10dip"
      android:text="@string/btn_label"
      android:onClick="onClick" /&gt;
      
  &lt;TextView
      android:id="@+id/tvId"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content" 
      android:layout_marginTop="10dip" /&gt;
      
&lt;/LinearLayout&gt;
</pre>

<p>
This is <i>main.xml</i> file. We have a Button widget and a
TextView widget. The button will show a PopupMenu.
</p>

<div class="codehead">strings.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;resources&gt;
    &lt;string name="app_name"&gt;PopupMenu&lt;/string&gt;
    &lt;string name="btn_label"&gt;Show menu&lt;/string&gt;
    &lt;string name="pm1"&gt;Item 1&lt;/string&gt;
    &lt;string name="pm2"&gt;Item 2&lt;/string&gt;
&lt;/resources&gt;
</pre>

<p>
This is the <i>strings.xml</i> resource file. 
</p>

<div class="codehead">popup_menu.xml</div>
<pre class="code">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  &lt;item android:id="@+id/settings"
    android:title="@string/pm1" /&gt;
  &lt;item android:id="@+id/tools"
    android:title="@string/pm2" /&gt;
&lt;/menu&gt;
</pre>

<p>
This is <i>popup_menu.xml</i> file. It defines two menu items. The file
is located in the res/menu/ subdirectory.
</p>

<div class="codehead">MainActivity.java</div>
<pre class="code">
package com.zetcode.popmenu;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;

public class MainActivity extends Activity
    implements OnMenuItemClickListener
{   
    private TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tv = (TextView) findViewById(R.id.tvId);        
    }

   public void onClick(View v) 
   {   
       showPopupMenu(v);
   }

   public void showPopupMenu(View v)
   {
       PopupMenu pm = new PopupMenu(MainActivity.this, v);
       pm.getMenuInflater().inflate(R.menu.popup_menu, pm.getMenu()); 
       pm.setOnMenuItemClickListener(this);          
       pm.show();
   }

   @Override
   public boolean onMenuItemClick(MenuItem item) 
   {           
      tv.setText(item.toString() + " selected");
      return true;  
   }
}
</pre>

<p>
A PopupMenu is displayed after clicking on the button widget.
</p>

<pre class="explanation">
public void onClick(View v) 
{   
    showPopupMenu(v);
}
</pre>

<p>
This method is a callback to the button click. The relation is set in the main.xml file
via an attribute. The method calls the showPopupMenu() method.
</p>

<pre class="explanation">
public void showPopupMenu(View v)
{
    PopupMenu pm = new PopupMenu(MainActivity.this, v);
    pm.getMenuInflater().inflate(R.menu.popup_menu, pm.getMenu()); 
    pm.setOnMenuItemClickListener(this);          
    pm.show();
}
</pre>

<p>
We create an instance of the <code>PopupMenu</code> class. It builds the 
menu, sets the <code>OnMenuItemClickListener</code> and shows the <code>PopupMenu</code>.
</p>

<pre class="explanation">
@Override
public boolean onMenuItemClick(MenuItem item) 
{           
    tv.setText(item.toString() + " selected");
    return true;  
}
</pre>

<p>
After selecting a menu item the <code>onMenuItemClick()</code> method is called.
It sets the item's title to the TextView widget.
</p>


<p>
In this chapter of the Android development tutorial, we have worked with menus.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br> 



<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified November 26, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

